package de.klenkse.eclipse.ftpsync.synchronizer;

import java.util.LinkedList;
import java.util.Queue;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;

/**
 * Resource change listener which generates and dispatches commands for the
 * command processors.
 */
public class CommandGenerationHandler implements IResourceChangeListener {

	/**
	 * The synchronization manager.
	 */
	private SynchronizationManager syncManager;

	/**
	 * Constructor.
	 */
	public CommandGenerationHandler(SynchronizationManager syncManager) {
		this.syncManager = syncManager;
	}

	/** {@inheritDoc} */
	@Override
	public void resourceChanged(IResourceChangeEvent event) {
		// debug : print all change deltas.
		Queue<IResourceDelta> queue = new LinkedList<IResourceDelta>();
		queue.add(event.getDelta());
		while (!queue.isEmpty()) {
			IResourceDelta delta = queue.poll();
			if (syncManager.getConfigEntries().containsKey(delta.getResource())) {
				generateCommands(delta, syncManager.getConfigEntries().get(
						delta.getResource()), "./");
			}
			for (IResourceDelta d : delta.getAffectedChildren()) {
				queue.add(d);
			}
		}
	}

	/**
	 * Generates a set of commands for a given {@link IResourceDelta} and
	 * dispatches the commands to a {@link CommandProcessor}.
	 */
	private void generateCommands(IResourceDelta delta,
			CommandProcessor commandProcessor, String relativePath) {
		for (IResourceDelta childDelta : delta.getAffectedChildren()) {
			String currentRelPath = relativePath
					+ childDelta.getResource().getName();
			if (childDelta.getResource() instanceof IFolder) {
				currentRelPath += "/";
			}
			ResourceCommand command = ResourceCommandFactory
					.getCommandForDelta(childDelta, currentRelPath);
			commandProcessor.executeCommand(command);
			if (!(command instanceof ResourceRemoveCommand)) {
				// remove commands work recursively.
				generateCommands(childDelta, commandProcessor, currentRelPath);
			}
		}
	}
}
